--#include "data\config\activityconfig\Carnival\CarnivalConfig.lua" once 

Carnival_Rank_Type_Circle_1 = 1
Carnival_Rank_Type_Swing_2 = 2
Carnival_Rank_Type_HeroRune_3  = 3
Carnival_Rank_Type_StoveDiamond_4 = 4
Carnival_Rank_Type_StoveSealBead_5 = 5
Carnival_Rank_Type_BattlePower_6 = 6

Carnival_Act_Type_OpenServeRank_1 = 1
Carnival_Act_Type_WishingPool_2 = 2
Carnival_Act_Type_Boss_3 = 3
Carnival_Act_Type_rentBuff_4 = 4
Carnival_Act_Type_ConsumeReturn_5 = 5 


--1:开服排行 2：许愿池 3：神装boss 4：神力租赁 5消费返利)
function CarnivalGetData(sysarg, packet)
	local nActType = DataPack.readByte(packet)
	local nSub = DataPack.readByte(packet)
	if nActType == Carnival_Act_Type_OpenServeRank_1 then
		CarnivalSendOpenServerRankData(sysarg, nSub)
	elseif nActType == Carnival_Act_Type_WishingPool_2 then
        CarnivalSendWishingPoolData(sysarg)
    elseif nActType == Carnival_Act_Type_Boss_3 then
        CarnivalSendBossData(sysarg)
    elseif nActType == Carnival_Act_Type_rentBuff_4 then
        CarnivalSendRentBuffData(sysarg)
    elseif nActType == Carnival_Act_Type_ConsumeReturn_5 then
        CarnivalSendConsumeReturnData(sysarg)
	end
end

--获取配置
function GetCarnivalCfg(nActType, nSub)
	if nActType == Carnival_Act_Type_OpenServeRank_1 then
		return CarnivalConfig.OpenServerRank, nSub and CarnivalConfig.OpenServerRank.Theme[nSub] or nil
	elseif nActType == Carnival_Act_Type_WishingPool_2 then
		return CarnivalConfig.WishingPool
	elseif nActType == Carnival_Act_Type_Boss_3 then
		return CarnivalConfig.Boss
	elseif nActType == Carnival_Act_Type_rentBuff_4 then
		return CarnivalConfig.rentBuff
	elseif nActType == Carnival_Act_Type_ConsumeReturn_5 then
		return CarnivalConfig.ConsumeReturn
	end
end
--是否在活动期间之内
function IsInCarnivalDay(nActType, nSub)
    local openday = System.getDaysSinceOpenServer()
    local cfg,subCfg = GetCarnivalCfg(nActType, nSub)
    if subCfg then
    	if openday >= subCfg.startDay and openday <= subCfg.endDay then
            if nActType == Carnival_Act_Type_OpenServeRank_1 then
                local ssVar = System.getStaticVar()    
                if ssVar.carnival_openServerRank_end and ssVar.carnival_openServerRank_end[nSub] then
                    return false
                end
            end
            return true
        end
    elseif cfg then
    	return openday >= cfg.startDay and openday <= cfg.endDay
    end
    return false
end

--是否在创角活动时间内
function IsInCarnivalCreateTime(sysarg, nActType)
    local createDay = Actor.getDaysSinceCreateRole(sysarg)
    local cfg,subCfg = GetCarnivalCfg(nActType, nSub) 
    if cfg then
        return createDay >= cfg.createRoleStartDay and createDay <= cfg.createRoleEndDay
    end  
end

--开服排行触发计算
function OnCarnivalOpenServerRankTriggerEvent(sysarg, nRankType, nValue)
    local cfg,subCfg = GetCarnivalCfg(Carnival_Act_Type_OpenServeRank_1, nRankType)
    local openday = System.getDaysSinceOpenServer()
    if openday > subCfg.endDay then
        return
    end

   	local rank_def = _G["RANK_DEFINE_CARNIVAL_RANK_"..nRankType]
   	if not rank_def then
   		print("rank_def = nil rankType:",nRankType)
        return
   	end
    local actorid = Actor.getActorId(sysarg)
    if not gRankMgr_SetRank(actorid, rank_def, nValue) then
        gRankMgr_SetRankEx(actorid, rank_def, 1, Actor.getIntProperty(sysarg, PROP_ACTOR_VOCATION))
        gRankMgr_SetRankEx(actorid, rank_def, 2, Actor.getIntProperty(sysarg, PROP_ACTOR_SEX))
    end
end

--根据开服天数获取哪种开服排行
function CarnivalGetOpenServerRankType()
	local openday = System.getDaysSinceOpenServer()
	local dVar = System.getDyanmicVar()
	if dVar.carnivalOpenServerRankType then
		local subCfg = CarnivalConfig.OpenServerRank.Theme[dVar.carnivalOpenServerRankType]
		if openday >= subCfg.startDay and openday <= subCfg.endDay then
			return dVar.carnivalOpenServerRankType
		end
	end
	for i,subCfg in ipairs(CarnivalConfig.OpenServerRank.Theme) do
		if openday >= subCfg.startDay and openday <= subCfg.endDay then
			dVar.carnivalOpenServerRankType = i
			return i
		end
	end
end

--开服排行获取排名数据
function CarnivalGetOpenServerRankData(subCfg, nRankType, sysarg)
    local rank_def = _G["RANK_DEFINE_CARNIVAL_RANK_"..nRankType]
    local rankPtr = Ranking.getRanking(RankList[rank_def].strName)
    local rankData = {}
    local myRankData = {}
    if rankPtr then
        local rankCount = Ranking.getRankItemCount(rankPtr)
        for rankIndex = 1, rankCount do
            local item = Ranking.getItemFromIndex(rankPtr, rankIndex - 1)
            if item then
                local point = Ranking.getPoint(item)   
                if point < subCfg.rankMinValue then
                    break
                else
                   table.insert(rankData,
                    {
                        actorId =Ranking.getId(item),
                        rankId = rankIndex, 
                        value = point,
                        name = Ranking.getSub(item, 0), 
                        job = tonumber(Ranking.getSub(item, 1)), 
                        sex = tonumber(Ranking.getSub(item, 2)), 
                    })
                end
            end
        end
    end
    if sysarg then
       myRankData= {rank = Ranking.getItemIndexFromId(rankPtr, Actor.getActorId(sysarg))+1}
    end
    return rankData,myRankData
end

--开服排行下发数据
function CarnivalSendOpenServerRankData(sysarg, nRankType)
	local nRankType = nRankType or CarnivalGetOpenServerRankType()
	local subCfg = CarnivalConfig.OpenServerRank.Theme[nRankType]
	if not subCfg then
		return
	end
    local rankData, myRankData = CarnivalGetOpenServerRankData(subCfg, nRankType, sysarg)

    local npack = DataPack.allocPacket(sysarg,LogicCmd.activitySys.sysId, LogicCmd.activitySys.sub.sSendCarnivalOpenServerRank)
    if not npack then return end
    DataPack.writeByte(npack, nRankType)
    local sendNum = #rankData > subCfg.rankShowNum and subCfg.rankShowNum or #rankData
    DataPack.writeByte(npack, sendNum)
    for i=1,sendNum do
        DataPack.writeByte(npack, rankData[i].rankId)
        DataPack.writeString(npack, rankData[i].name)
    end
    DataPack.writeInt(npack, myRankData.rank)
    DataPack.flush(npack) 
end

--开服排行结束
function CarnivalOpenServerEnd()
    local nRankType =  CarnivalGetOpenServerRankType()
    if not IsInCarnivalDay(Carnival_Act_Type_OpenServeRank_1, nRankType) then
        return
    end
    local subCfg = CarnivalConfig.OpenServerRank.Theme[nRankType]
    if not subCfg then
        return
    end
    local openday = System.getDaysSinceOpenServer()
    if openday ~= subCfg.endDay then
        return
    end
    print("CarnivalOpenServerEnd :",nRankType)
    local ssVar = System.getStaticVar()
    if not ssVar.carnival_openServerRank_end then
       ssVar.carnival_openServerRank_end = {}
    end
    ssVar.carnival_openServerRank_end[nRankType] = 1
    local rankData = CarnivalGetOpenServerRankData(subCfg, nRankType)
    local awardIndex = 1
    for i,v in ipairs(rankData) do
        for a_i = awardIndex, #subCfg.RankAward do
            local rankCfg = subCfg.RankAward[a_i]
            if v.rankId >= rankCfg.cond[1] and v.rankId <= rankCfg.cond[2] then
                local title = string.format(Lang.ScriptTips.Carnival012, subCfg.name)
                local content = string.format(Lang.ScriptTips.Carnival013, subCfg.name, v.rankId)
                local nActorJob = v.job
                local nActorSex = v.sex
                Awards.GiveToMailById(v.actorId, rankCfg.awards, title, content, LogIds.CarnivalOpenServerRankLogId, Lang.LogTips.CarnivalOpenServerRankLogId, nActorJob, nActorSex)
                print("send Carnival Mail = v.actorid "..v.actorId .."  rank:"..v.rankId.." job :"..nActorJob.." sex:"..nActorSex)
                break
            end
            awardIndex = a_i
        end
    end
end

--许愿池下发数据
function CarnivalSendWishingPoolData(sysarg)
    local nActorId = Actor.getActorId(sysarg)   
    local itemData = BaseFuc_unserialize(gRankMgr_GetValueById(nActorId, RANK_DEFINE_CARNIVAL_WISHING_POOL, 1)) or {}
    gRankMgr_Save(RANK_DEFINE_CARNIVAL_WISHING_POOL)
    local npack = DataPack.allocPacket(sysarg,LogicCmd.activitySys.sysId, LogicCmd.activitySys.sub.sSendCarnivalWishingPoolData)
    if not npack then return end
    DataPack.writeByte(npack, #itemData)
    for i,v in ipairs(itemData) do
        DataPack.writeByte(npack, v.type)
        DataPack.writeShort(npack, v.id)
        DataPack.writeInt(npack, v.count)
    end
    
    DataPack.flush(npack) 

end

--投入物品到许愿池
function CarnivalPutItemToWishingPool(sysarg, packet)
    local nIndex = DataPack.readByte(packet)
    if not IsInCarnivalDay(Carnival_Act_Type_WishingPool_2) then
        Actor.sendTipmsg(sysarg, Lang.ScriptTips.Carnival015, ttFlyTip)
        return
    end
    
    local nActorId = Actor.getActorId(sysarg)   
    local itemData = BaseFuc_unserialize(gRankMgr_GetValueById(nActorId, RANK_DEFINE_CARNIVAL_WISHING_POOL, 1)) or {}
    if #itemData >= CarnivalConfig.WishingPool.wishMaxCount then        
       Actor.sendTipmsg(sysarg, string.format(Lang.ScriptTips.Carnival014, CarnivalConfig.WishingPool.wishMaxCount), ttFlyTip)
       return 
    end
    local consume =  CarnivalConfig.WishingPool.Items[nIndex]
    if not consume then
        Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0001, ttFlyTip)
        return
    end
    local logId,logStr = LogIds.CarnivalWishingPoolLogId, Lang.LogTips.CarnivalWishingPoolLogId
    if not CheckConsumeCond(sysarg, {consume}) then
        return
    end
    if not DoConsumeCond( sysarg, {consume}, 1, logId,logStr, false ) then
        return
    end
    table.insert(itemData, consume)
    gRankMgr_SetRankEx(nActorId, RANK_DEFINE_CARNIVAL_WISHING_POOL, 1, BaseFuc_serialize(itemData))
    CarnivalSendWishingPoolData(sysarg)
end

--许愿池结束返还双倍
function CarnivalWishingPoolEnd()
    local openday = System.getDaysSinceOpenServer()
    local cfg = CarnivalConfig.WishingPool
    if openday <= cfg.startDay and openday > (cfg.endDay + 1) then
        return
    end
    local rankPtr = Ranking.getRanking(RankList[RANK_DEFINE_CARNIVAL_WISHING_POOL].strName)
    local rankCount = Ranking.getRankItemCount(rankPtr)
    for idx = 1, rankCount do
        local item = Ranking.getItemFromIndex(rankPtr, idx-1)
        if item then
            local nActorId = tonumber(Ranking.getId(item))
            local itemData = BaseFuc_unserialize(Ranking.getSub(item, 1))
            local awards = GetAwardsByRate(itemData, CarnivalConfig.WishingPool.wishItemReturnRate)
            local title = Lang.ScriptTips.Carnival016
            local content = Lang.ScriptTips.Carnival017
            local logId,logStr = LogIds.CarnivalWishingPoolLogId, Lang.LogTips.CarnivalWishingPoolLogId
            Awards.GiveToMailById(nActorId, awards, title, content, logId,logStr)
        end
    end
    gRankMgr_Clear(RANK_DEFINE_CARNIVAL_WISHING_POOL)
end


function ResisteCarnivalBossProc()
    SceneExitDispatcher.register(CarnivalConfig.Boss.sceneId, OnCommonSceneExit )                  --注册离开场景、副本后触发的事件
end
ResisteCarnivalBossProc()

function CarnivalBossStart()
    if not IsInCarnivalDay(Carnival_Act_Type_Boss_3) then
        return
    end
    local openday = System.getDaysSinceOpenServer()
    local cfg,subCfg = GetCarnivalCfg(Carnival_Act_Type_Boss_3, nSub)
    local act_day = openday - cfg.startDay + 1
    local dVar = System.getDyanmicVar()
    dVar.carnivalBossStart = System.getCurrMiniTime()
    dVar.carnivalBossDie = nil
    for i,v in ipairs(CarnivalConfig.Boss.monsters) do
        clearScenceMonster(v)
    end
    local oneMonCfg = CarnivalConfig.Boss.monsters[act_day]
    if oneMonCfg then
        local monsters = {oneMonCfg}
        FreshCommonMonsters(monsters, 0, true )
    end
   
    local playerList = LuaHelp.getAllActorList() or {}
    for i,v in ipairs(playerList) do
        CarnivalSendBossData(v)
    end
end

function CarnvivalNewDay()
    local dVar = System.getDyanmicVar()
    dVar.carnivalBossDie = nil
end
function CarnivalBossEnd()
    if not IsInCarnivalDay(Carnival_Act_Type_Boss_3) then
        return
    end
    local dVar = System.getDyanmicVar()
    dVar.carnivalBossStart = nil
    local playerList = LuaHelp.getAllActorList() or {}
    for i,v in ipairs(playerList) do
        Actor.returnCity(v)
        CarnivalSendBossData(v)
    end
end
function CarnivalSendBossData(sysarg)
    local dVar = System.getDyanmicVar()
    local npack = DataPack.allocPacket(sysarg,LogicCmd.activitySys.sysId, LogicCmd.activitySys.sub.sSendCarnivalBossData)
    if not npack then return end
    DataPack.writeByte(npack, dVar.carnivalBossStart and 1 or 0)
    DataPack.writeByte(npack, dVar.carnivalBossDie or 0)
    DataPack.flush(npack) 
end
function CarnivalEnterBoss(sysarg)
    local dVar = System.getDyanmicVar() 
    if not dVar.carnivalBossStart then
        Actor.sendTipmsg(sysarg, Lang.ScriptTips.Carnival015, ttFlyTip)
        return
    end
    local bossCfg = CarnivalConfig.Boss
    local openday = System.getDaysSinceOpenServer()
    local levelCfg = bossCfg.enterLevelLimit[openday]
    if not levelCfg then
        Actor.sendTipmsg(sysarg, Lang.ScriptTips.Carnival015, ttFlyTip)
        return
    end
    if not Actor.checkActorLevel(sysarg, levelCfg[2], levelCfg[1]) then
        Actor.sendTipmsg(sysarg, string.format(Lang.ScriptTips.Carnival019, levelCfg[1]), ttFlyTip)
        return
    end

    local logId,logStr = LogIds.CarnivalBossLogId, Lang.LogTips.CarnivalBossLogId
    if CommonEnterScence( sysarg, bossCfg, logId, logStr ) then
        
        InitCarnivalBoss(sysarg, bossCfg)

        Actor.closeDialogs( sysarg, enLinkCarnivalWnd ) 
    end
end

function InitCarnivalBoss(sysarg, bossCfg)
    local dVar = System.getDyanmicVar()
    local startTime = dVar.carnivalBossStart or System.getCurrMiniTime()
    local restTime = startTime + bossCfg.beInTime - System.getCurrMiniTime()
    InitOnlyButtonPanel( sysarg, 2, enRightPanelActivity_CarnivalBoss, restTime, Lang.ScriptTips.Carnival018 )
end


function OnCarnivalBossDie(monster, sysarg, monId, lastHitKiller)
    local sceneId = Actor.getSceneId( monster )
    if sceneId ~= CarnivalConfig.Boss.sceneId then
        return
    end

    local dVar = System.getDyanmicVar()
    dVar.carnivalBossDie = 1
    local playerList = LuaHelp.getAllActorList() or {}
    for i,v in ipairs(playerList) do
        CarnivalSendBossData(v)
    end
end


function CarnivalBuyBuff(sysarg, packet)
    local buffIndex = DataPack.readByte(packet)
    if not IsInCarnivalCreateTime(sysarg, Carnival_Act_Type_rentBuff_4) then
        Actor.sendTipmsg(sysarg, Lang.ScriptTips.Carnival020, ttFlyTip)
        return
    end
    local buffCfg = CarnivalConfig.rentBuff.BuffList[buffIndex]
    if not buffCfg then
        Actor.sendTipmsg(sysarg, Lang.ScriptTips.COM0001, ttFlyTip)
        return
    end
    local aVar = Actor.getStaticVar(sysarg)
    if not aVar.carnivalBuff then
        aVar.carnivalBuff = {}
    end
    if aVar.carnivalBuff[buffIndex] then
        Actor.sendTipmsg(sysarg, Lang.ScriptTips.Carnival021, ttFlyTip)
        return 
    end
    local consumes = {{type = qatYuanbao, id = 0, count = buffCfg.yb}}
    local logId,logStr = LogIds.CarnivalRentBuffLogId, Lang.LogTips.CarnivalRentBuffLogId
    if not CheckConsumeCond(sysarg, consumes) then
        return
    end
    if not DoConsumeCond( sysarg, consumes, 1, logId,logStr, false ) then
        return
    end
    for i,v in ipairs(buffCfg.BuffId) do
       Actor.addBuffById(sysarg, v)
    end
    aVar.carnivalBuff[buffIndex] = 1
    CarnivalSendRentBuffData(sysarg)

    local sysMsg = string.format(Lang.ScriptTips.Carnival025, Actor.getName(sysarg), buffCfg.name)
    System.broadcastTipmsg(sysMsg, ttChatWindow + ttScreenCenter)
end

function CarnivalSendRentBuffData(sysarg)
    local aVar = Actor.getStaticVar(sysarg)
    if not aVar.carnivalBuff then
        aVar.carnivalBuff = {}
    end
    local npack = DataPack.allocPacket(sysarg,LogicCmd.activitySys.sysId, LogicCmd.activitySys.sub.sSendCarnivalRentBuff)
    if not npack then return end
    DataPack.writeByte(npack, #CarnivalConfig.rentBuff.BuffList)
    for i,v in ipairs(CarnivalConfig.rentBuff.BuffList) do
        DataPack.writeByte(npack, aVar.carnivalBuff[i] or 0)
    end
    DataPack.flush(npack)  
end

function  OnCarnivalBuffYbReturnCrossDay(sysarg)
    if IsInCarnivalCreateTime(sysarg, Carnival_Act_Type_rentBuff_4) then
        return
    end
    local createDay = Actor.getDaysSinceCreateRole(sysarg)
    if createDay <= CarnivalConfig.rentBuff.createRoleEndDay then
        return
    end 
    local aVar = Actor.getStaticVar(sysarg)
    if aVar.carnivalBuff then
        local totalYb = 0
        for i,v in ipairs(CarnivalConfig.rentBuff.BuffList) do
            if aVar.carnivalBuff[i] then
                totalYb = totalYb + v.yb
            end
        end
        if totalYb > 0 then
            local title = Lang.ScriptTips.Carnival026
            local content = Lang.ScriptTips.Carnival027
            local awards = {{type = qatYuanbao, id = 0, count = totalYb}}
            local logId,logStr = LogIds.CarnivalRentBuffLogId, Lang.LogTips.CarnivalRentBuffLogId
            Awards.GiveToMailById(Actor.getActorId(sysarg), awards, title, content, logId,logStr)
        end
        aVar.carnivalBuff = nil
    end
end

function OnCarnivalCrossDay(sysarg)
    OnCarnivalBuffYbReturnCrossDay(sysarg)
    OnCarnivalConsumeReturnCrossDay(sysarg)
end

function OnCarnivalConsumeYuanbao(sysarg, nYuanBao)
    OnCarnivalConsumeReturn(sysarg, nYuanBao)
end

function OnCarnivalConsumeReturn(sysarg, nYuanBao)
    if not IsInCarnivalCreateTime(sysarg, Carnival_Act_Type_ConsumeReturn_5) then
        return
    end
    local aVar = Actor.getStaticVar(sysarg)
    aVar.carnivalConsumeYb = (aVar.carnivalConsumeYb or 0 ) + nYuanBao
    CarnivalSendConsumeReturnData(sysarg)
end

function CarnivalSendConsumeReturnData(sysarg)
    local aVar = Actor.getStaticVar(sysarg)
    local npack = DataPack.allocPacket(sysarg,LogicCmd.activitySys.sysId, LogicCmd.activitySys.sub.sSendCarnivalConsumeReturn)
    if not npack then return end
    DataPack.writeInt(npack, aVar.carnivalConsumeYb or 0)
    DataPack.flush(npack)  
end

function OnCarnivalConsumeReturnCrossDay(sysarg)
    if IsInCarnivalCreateTime(sysarg, Carnival_Act_Type_ConsumeReturn_5) then
        return
    end
    local createDay = Actor.getDaysSinceCreateRole(sysarg)
    if createDay <= CarnivalConfig.ConsumeReturn.createRoleEndDay then
        return
    end 
    local aVar = Actor.getStaticVar(sysarg)
    local config = CarnivalConfig.ConsumeReturn
    if  aVar.carnivalConsumeYb then
        for ii = 1, #config.Awards do
            if aVar.carnivalConsumeYb >= config.Awards[ii].rechargeLimitNum then
                local awardNum = math.floor(config.Awards[ii].awardFactor * aVar.carnivalConsumeYb)
                local awardType = config.Awards[ii].awardType
                local rewards = {{ type = awardType, count = awardNum, bind = 0},}

                local title = Lang.ScriptTips.Carnival028
                local content = Lang.ScriptTips.Carnival029
                Awards.GiveToMailById(Actor.getActorId(sysarg), rewards, title, content, LogIds.CarnivalConsumeReturnLogId, Lang.LogTips.CarnivalConsumeReturnLogId)
                break
            end
        end
         aVar.carnivalConsumeYb = nil
    end
end

